/***************************************************************************
 *   Copyright (C) 2007 by Ivan Vasić              *
 *   ivasic@gmail.com                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "announcerequest.h"
#include "sha1hash.h"
#include "exceptions.h"
				
#include <QDebug>
#include <QString>
#include <QStringList>
#include <QByteArray>
#include <QTcpSocket>
#include <QHostAddress>
		
AnnounceRequest::AnnounceRequest(const QHttpRequestHeader& request, QTcpSocket* socket)
	: m_socket(socket)
{
	setType(Request::ANNOUNCE);
	
	m_url = QUrl::fromEncoded(request.path().toAscii());
	m_userAgent = request.value("User-Agent");
	m_passkey = request.path().section('/', -2, -2);
	
	if(m_passkey.isEmpty() || m_passkey.length() < 20)
		throw new Exception("Bad passkey.", Exception::Normal, __FILE__, __FUNCTION__, __LINE__);
}

AnnounceRequest::~AnnounceRequest()
{}

bool AnnounceRequest::isValid() const
{
	if(left() == 0xFFFFFFFF || downloaded() == 0xFFFFFFFF || uploaded() == 0xFFFFFFFF)
	{
		qDebug() << "Left, downloaded or uploaded field omitted in announce request! " << m_url;
		return false;
	}
	
	if(ip() == QHostAddress::Null || peerID().isEmpty())
	{
		qDebug() << "IP or PEER_ID field omitted in announce request! "  << m_url;
		return false;
	}
	
	/* ISKULIRAJ ZBOG QT4 EXAMPLEa
	if(m_userAgent == QString::null)
		return false;*/
	
	if(event() == EVENT_NOT_SET)
	{
		qDebug() << "Event field omitted in announce request! " << m_url;
		return false;
	}
		
	if(port() == 0)
	{
		qDebug() << "Port field omitted in announce request! " << m_url;
		return false;
	}
	
	
	return true;
}


QString AnnounceRequest::announceEventToString(AnnounceEvent event)
{
	switch(event)
	{
		case EVENT_NOT_SET:
			return "NOT SET";
		case EVENT_STARTED:
			return "started";
		case EVENT_STOPPED:
			return "stopped";
		case EVENT_COMPLETED:
			return "completed";
		case EVENT_EMPTY:
			return "";
	}
	
	return QString::null;
}

QByteArray AnnounceRequest::peerID() const
{
	return m_url.queryItemValue("peer_id").toUtf8();
}

quint16 AnnounceRequest::port() const
{
	bool ok = true;
	quint16 port = m_url.queryItemValue("port").toUShort(&ok);
	
	return ok ? port : 0;
}

quint64 AnnounceRequest::downloaded() const
{
	bool ok = true;
	quint64 val = m_url.queryItemValue("downloaded").toULongLong(&ok);
	
	return ok ? val : 0xFFFFFFFF;
}

quint64 AnnounceRequest::left() const
{
	bool ok = true;
	quint64 val = m_url.queryItemValue("left").toULongLong(&ok);
	
	return ok ? val : 0xFFFFFFFF;
}

quint64 AnnounceRequest::uploaded() const
{
	bool ok = true;
	quint64 val = m_url.queryItemValue("uploaded").toULongLong(&ok);
	
	return ok ? val : 0xFFFFFFFF;
}

bool AnnounceRequest::compact() const
{
	bool ok = true;
	bool val = (bool) m_url.queryItemValue("downloaded").toInt(&ok);
	
	return ok ? val : true; //nek' vraca uvek compact response iako ima greske (valjda zovem isValid() da proverim posle...)
}

QString AnnounceRequest::key() const
{
	return m_url.queryItemValue("key");
}

int AnnounceRequest::numwant() const
{
	bool ok = true;
	int val = m_url.queryItemValue("uploaded").toInt(&ok);
	
	return ok ? val : 30;
}

const QString& AnnounceRequest::userAgent() const
{
	return m_userAgent;
}

QTcpSocket* AnnounceRequest::socket() const
{
	return m_socket;
}

SHA1Hash AnnounceRequest::infohash() const
{
	return SHA1Hash(m_url.queryItemValue("info_hash").toUtf8());
}

AnnounceEvent AnnounceRequest::event() const
{
	QString ev = m_url.queryItemValue("event");
	
	if(ev == QString::null)
		return EVENT_EMPTY;
	
	if(ev.toLower() == "started")
		return EVENT_STARTED;
	
	if(ev.toLower() == "stopped")
		return EVENT_STOPPED;
	
	if(ev.toLower() == "completed")
		return EVENT_COMPLETED;
	
	return EVENT_NOT_SET;
}

QHostAddress AnnounceRequest::ip() const
{
	if(m_url.queryItemValue("ip") != QString::null)
		return QHostAddress(m_url.queryItemValue("ip"));
	
	return m_socket->peerAddress();
}

QByteArray AnnounceRequest::passkey() const
{
	return m_passkey.toAscii();
}
